package net.xdclass.shopproject;

//import net.xdclass.config.SmsProperties;
import net.xdclass.shopproject.domain.Product;
import net.xdclass.shopproject.spring.ClassPathXmlApplicationContext;
import net.xdclass.shopproject.spring.ProductMapper;
import net.xdclass.shopproject.spring.ProductServiceImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class ShopProjectApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(ShopProjectApplication.class, args);

        /*simulateSpringFramework();*/

//        factroyBeanTest();

//        testCircularReferences();

    }

//    @Bean
//    public SmsProperties smsProperties() {
//        return new SmsProperties();
//    }

    /**
     * 模拟简易版spring
     *
     * @throws Exception
     */
    public static void simulateSpringFramework() throws Exception {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();
        ProductMapper productMapper = (ProductMapper) applicationContext.getBean("productMapper");
        System.out.println(productMapper.findNameById(888));

        ProductServiceImpl productServiceImpl = (ProductServiceImpl) applicationContext.getBean("productServiceImpl");
        String productById = productServiceImpl.findProductById(999);
        System.out.println(productById);
    }

    /**
     * FactoryBean接口应用
     */
    public static void factroyBeanTest() {
        org.springframework.context.support.ClassPathXmlApplicationContext applicationContext
                = new org.springframework.context.support.ClassPathXmlApplicationContext("classpath*:application.xml");
        // 因为实现了FactoryBean接口，所以这里getBean获取的时候会调用FactoryBean的getObject方法，从getObject方法中返回对象
        Product product = (Product) applicationContext.getBean("product");
        System.out.println(product);
        // 获取FactoryBean，加上&符号
//        System.out.println(applicationContext.getBean("&product"));
    }

    public static void beanFactoryPostProcessor() {
        org.springframework.context.support.ClassPathXmlApplicationContext applicationContext
                = new org.springframework.context.support.ClassPathXmlApplicationContext("classpath*:application.xml");
        applicationContext.getBean("productService");
    }

    /**
     * 循环依赖
     * 1、调用构造函数实例化后，提前暴露，放到三级缓存中，发现自己的属性有依赖B对象
     * 2、创建B对象过程中，发现自己的属性依赖A对象，从三级缓存获取未成年的A对象，且转移到二级缓存
     * 3、有后置处理器，可以做扩展操作
     * 4、创建好B对象后，将B对象加入到一级缓存中
     * 5、A对象使用一级缓存中的B对象
     */
    public static void testCircularReferences() {
        org.springframework.context.support.ClassPathXmlApplicationContext applicationContext
                = new org.springframework.context.support.ClassPathXmlApplicationContext("classpath*:application.xml");
        applicationContext.getBean("aService");
    }
}
